home *** CD-ROM | disk | FTP | other *** search
/ Aminet 34 / Aminet 34 (2000)(Schatztruhe)[!][Dec 1999].iso / Aminet / util / gnu / unixcmds.lha / unixcmds / src / comm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-06  |  5.1 KB  |  221 lines

  1. /* comm - select lines from two sorted files    Author: Martin C. Atkins */
  2.  
  3. /*
  4.  *      This program was written by:
  5.  *              Martin C. Atkins,
  6.  *              University of York,
  7.  *              Heslington,
  8.  *              York. Y01 5DD
  9.  *              England
  10.  *      and is released into the public domain, on the condition
  11.  *      that this comment is always included without alteration.
  12.  */
  13.  
  14. #include <sys/types.h>
  15. #include <fcntl.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <unistd.h>
  19. #include <stdio.h>
  20.  
  21. #define BUFFER_SIZE (512)
  22. #define LINMAX (600)
  23.  
  24. struct file {
  25.   char *name;                   /* the file's name */
  26.   int fd;                       /* the file descripter */
  27.   char buf[BUFFER_SIZE];                /* buffer storage */
  28.   char *next;                   /* the next character to read */
  29.   char *endp;                   /* the first invalid character */
  30.   int seeneof;                  /* an end of file has been seen */
  31. } files[2];
  32.  
  33. char lines[2][LINMAX];
  34.  
  35. int colflgs[3] = {1, 2, 3};     /* number of tabs + 1: 0 => no column */
  36.  
  37. static char *umsg = "Usage: comm [-[123]] file1 file2\n";
  38.  
  39. int main  (int argc, char **argv);
  40. void usage  (void);
  41. void error  (char *s, char *f);
  42. void eopen  (char *fn, struct file *file);
  43. int getbuf  (struct file *file);
  44. int readline  (int fno);
  45. void comm  (void);
  46. void putcol  (int col, char *buf);
  47. void cpycol  (int col);
  48.  
  49. int main(argc, argv)
  50. /* [<][>][^][v][top][bottom][index][help] */
  51. int argc;
  52. char *argv[];
  53. {
  54.   int cnt;
  55.   if (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
  56.         char *ap;
  57.         for (ap = &argv[1][1]; *ap; ap++) switch (*ap) {
  58.                     case '1':
  59.                     case '2':
  60.                     case '3':
  61.                         cnt = *ap - '1';
  62.                         if (colflgs[cnt] == 0) break;
  63.                         colflgs[cnt] = 0;
  64.                         for (cnt++; cnt < 3; cnt++) colflgs[cnt]--;
  65.                         break;
  66.                     default:    usage();
  67.                 }
  68.         argc--;
  69.         argv++;
  70.   }
  71.   if (argc != 3) usage();
  72.   eopen(argv[1], &files[0]);
  73.   eopen(argv[2], &files[1]);
  74.   comm();
  75.   return(0);
  76. }
  77.  
  78. void std_err(char *str)
  79. {
  80.   fprintf(stderr,str);
  81. }
  82.  
  83. void usage()
  84. /* [<][>][^][v][top][bottom][index][help] */
  85. {
  86.  
  87.   std_err(umsg);
  88.   exit(1);
  89. }
  90.  
  91. void error(s, f)
  92. /* [<][>][^][v][top][bottom][index][help] */
  93. char *s, *f;
  94. {
  95.   std_err("comm: ");
  96.   std_err(s);
  97.   if (f) std_err(f);
  98.   std_err("\n");
  99.   exit(1);
  100. }
  101.  
  102. void eopen(fn, file)
  103. /* [<][>][^][v][top][bottom][index][help] */
  104. char *fn;
  105. struct file *file;
  106. {
  107.   file->name = fn;
  108.   file->next = file->endp = &file->buf[0];
  109.   file->seeneof = 0;
  110.   if (fn[0] == '-' && fn[1] == '\0')
  111.         file->fd = 0;
  112.   else if ((file->fd = open(fn, O_RDONLY)) < 0)
  113.         error("can't open ", fn);
  114. }
  115.  
  116.  
  117. int getbuf(file)
  118. /* [<][>][^][v][top][bottom][index][help] */
  119. struct file *file;
  120. {
  121. /* Get a buffer-full from the file.  Return true if no characters
  122.  * were obtained because we are at end of file.
  123.  */
  124.   int n;
  125.  
  126.   if (file->seeneof) return(1);
  127.   if ((n = read(file->fd, &file->buf[0], BUFFER_SIZE)) < 0)
  128.         error("read error on ", file->name);
  129.   if (n == 0) {
  130.         file->seeneof++;
  131.         return 1;
  132.   }
  133.   file->next = &file->buf[0];
  134.   file->endp = &file->buf[n];
  135.   return(0);
  136. }
  137.  
  138.  
  139. int readline(fno)
  140. /* [<][>][^][v][top][bottom][index][help] */
  141. int fno;
  142. {
  143. /* Read up to the next '\n' character to buf.
  144.  * Return a complete line, even if end of file occurs within a line.
  145.  * Return false at end of file/
  146.  */
  147.   register struct file *file = &files[fno];
  148.   char *buf = lines[fno];
  149.  
  150.   if (file->next == file->endp && getbuf(file)) return(0);
  151.   while ((*buf++ = *file->next++) != '\n')
  152.         if (file->next == file->endp && getbuf(file)) {
  153.                 *buf++ = '\n';
  154.                 *buf = '\0';
  155.                 return(1);
  156.         }
  157.   *buf = '\0';
  158.   return(1);
  159. }
  160.  
  161. void comm()
  162. /* [<][>][^][v][top][bottom][index][help] */
  163. {
  164.   register int res;
  165.  
  166.   if (!readline(0)) {
  167.         cpycol(1);
  168.         return;
  169.   }
  170.   if (!readline(1)) {
  171.         putcol(0, lines[0]);
  172.         cpycol(0);
  173.         return;
  174.   }
  175.   for (;;) {
  176.         if ((res = strcmp(lines[0], lines[1])) != 0) {
  177.                 res = res > 0;
  178.                 putcol(res, lines[res]);
  179.                 if (!readline(res)) {
  180.                         putcol(!res, lines[!res]);
  181.                         cpycol(!res);
  182.                         return;
  183.                 }
  184.         } else {
  185.                 putcol(2, lines[0]);    /* files[1]lin == f2lin */
  186.                 if (!readline(0)) {
  187.                         cpycol(1);
  188.                         return;
  189.                 }
  190.                 if (!readline(1)) {
  191.                         putcol(0, lines[0]);
  192.                         cpycol(0);
  193.                         return;
  194.                 }
  195.         }
  196.   }
  197.  
  198.   /* NOTREACHED */
  199. }
  200.  
  201. void putcol(col, buf)
  202. /* [<][>][^][v][top][bottom][index][help] */
  203. int col;
  204. char *buf;
  205. {
  206.   int cnt;
  207.  
  208.   if (colflgs[col] == 0) return;
  209.   for (cnt = 0; cnt < colflgs[col] - 1; cnt++) printf("\t");
  210.   printf("%s", buf);
  211. }
  212.  
  213. void cpycol(col)
  214. /* [<][>][^][v][top][bottom][index][help] */
  215. int col;
  216. {
  217.   if (colflgs[col]) while (readline(col))
  218.                 putcol(col, lines[col]);
  219. }
  220. /* [<][>][^][v][top][bottom][index][help] */
  221.